<template>
  <div v-if="nvsData && nvsData.layout">
    <template v-if="showType === ConstDef.SHOW_TYPE_FORM">
      <template v-if="!nvsData.layout.cursive">
        <NvForm :nvData = "createNvData(nvsData.nvs,nvsData.nvs[0],nvsData.nd,nvsData.layout)" @define-event="handleEvent($event)" ref="refForm"></NvForm>
        <NvLayout :nvsData = "createNvsData(getChildNvs(nvsData.nvs[0],childLayout.ndName),getChildNd(nvsData.nd,childLayout.ndName),childLayout)" :key = "index" @define-event="handleEvent($event)" v-for = "(childLayout,index) in nvsData.layout.children">
        </NvLayout>
      </template>
      <template v-else>
        <NvCursiveForm :nvsData ="nvsData" @define-event="handleEvent($event)" ref="refForm"></NvCursiveForm>
        <NvLayout :nvsData = "createNvsData(getChildNvs(currentNv,childLayout.ndName),getChildNd(nvsData.nd,childLayout.ndName),childLayout)" :key = "index" @define-event="handleEvent($event)" v-for = "(childLayout,index) in nvsData.layout.children">
        </NvLayout>
      </template>
    </template>
    <template v-else-if="showType === ConstDef.SHOW_TYPE_GRID">
      <NvGrid :nvsData = "nvsData" ref="refGrid" @define-event="handleEvent($event)">
      </NvGrid>
      <NvLayout :nvsData = "createChildNvsData(currentNv,getChildNd(nvsData.nd,childLayout.ndName),childLayout)" :key = "index"  @define-event="handleEvent($event)" v-for = "(childLayout,index) in nvsData.layout.children">
      </NvLayout>
    </template>
    <template v-else-if="showType === ConstDef.SHOW_TYPE_TREE">
      <TreeLayout :nvs-data="nvsData" @define-event="handleEvent($event)"></TreeLayout>
    </template>
  </div>
</template>

<script>
import { ref, computed, watch } from 'vue'
import ConstDef from '../../js/ConstDef'
import NvForm from './NvForm'
import NvGrid from './NvGrid'
import NvCursiveForm from './NvCursiveForm'
import TreeLayout from './TreeLayout'
import { NvsDataCreator } from '../../js/NvsDataCreator'
import dataSourceUtils from '../../js/datasource/DataSourceUtils'
export default {
  name: 'NvLayout',
  components: {
    NvCursiveForm,
    NvForm,
    NvGrid,
    TreeLayout
  },
  props: {
    nvsData: {
      type: Object,
      default: null
    },
    isRootLayout: {
      type: Boolean,
      default: false
    }
  },

  setup(props) {
    const refGrid = ref();
    const refForm = ref();
    const dataSources = ref(new Map());
    const showType = computed(() => {
      return props.nvsData.layout.showType;
    })
    const currentNv = computed(() => {
      if (props.nvsData.layout.showType === ConstDef.SHOW_TYPE_FORM || props.nvsData.layout.showType === ConstDef.SHOW_TYPE_TREE) {
        if (refForm.value) return refForm.value.getCurrentNv(); else return null;
      } else {
        if (!refGrid.value) return null;
        const currentIndex = refGrid.value.getCurrentIndex();
        if (currentIndex.value < 0) {
          return null;
        } else {
          return props.nvsData.nvs[currentIndex.value];
        }
      }
    })

    const watchValues = computed(() => {
      if (!props.nvsData || !props.nvsData.layout || !currentNv.value) { return []; }
      const configs = dataSourceUtils.getDataSourceConfigs(props.nvsData.layout);
      const result = [];
      for (const config of configs) {
        const fdNames = dataSourceUtils.getWatchedFdNames(config);
        const kv = dataSourceUtils.getKVOfNv(currentNv.value, fdNames);
        result.push(kv);
      }
      return result;
    })

    watch(watchValues, async (newValue, oldValue) => {
      if (!props.nvsData || !props.nvsData.layout) { return; }
      const configs = dataSourceUtils.getDataSourceConfigs(props.nvsData.layout);
      for (const config of configs) {
        if (!currentNv.value) continue;
        const dataSource = await dataSourceUtils.getDataSource(config, currentNv.value);
        dataSources.value.set(config.name, dataSource);
      }
    })

    const { createNvData, createNvsData, createChildNvsData, getChildNvs, getChildNd, isNvLayout } = NvsDataCreator();
    return {
      showType,
      createNvData,
      createNvsData,
      createChildNvsData,
      getChildNvs,
      getChildNd,
      ConstDef,
      refGrid,
      refForm,
      currentNv,
      dataSources,
      isNvLayout
    }
  },
  methods: {
    getCurrentIndex() {
      if (this.refGrid) return this.refGrid.getCurrentIndex(); else return -1;
    },
    getCurrentNv() {
      if (this.nvsData.layout.showType === ConstDef.SHOW_TYPE_FORM || this.nvsData.layout.showType === ConstDef.SHOW_TYPE_TREE) {
        if (this.refForm) return this.refForm.getCurrentNv(); else return null;
      } else {
        if (!this.refGrid) return null;
        const currentIndex = this.refGrid.getCurrentIndex();
        let result = null;
        const nvs = this.nvsData.nvs;
        if (currentIndex.value >= 0) {
          result = nvs[currentIndex.value];
        }
        return result;
      }
    },

    getParentNvLayout () {
      if (this.isRootLayout) return null;
      let parent = this.$parent;
      while (parent != null) {
        if (parent.createNvData) { return parent; } else parent = parent.$parent;
      }
      return null;
    },

    getRootNvLayout () {
      if (this.isRootLayout) return this;
      return this.getParentNvLayout().getRootNvLayout();
    },

    getDataSource(name) {
      const dataSource = this.dataSources.get(name);
      if (dataSource) return dataSource;
      if (this.isRootLayout) { return null; } else { return this.getParentNvLayout().getDataSource(name); }
    },

    getSelectedNvs() {
      if (this.refGrid) return this.refGrid.getSelectedNvs(); else return [];
    },

    handleEvent(event) {
      this.$emit("define-event", event)
    }
  }

}
</script>

<style scoped>
</style>
